#include "StdAfx.h"
#include "MyNetwork.h"
//#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")

#include "AutoArchive.h"


static unsigned int __stdcall ThreadProc(void* pParam)
{
	CMyNetwork* pThis = (CMyNetwork*)pParam;
	pThis->Run();

	_endthreadex(0);

	return 0;
}

CMyNetwork::CMyNetwork(void)
{
	s_server = INVALID_SOCKET;
	ZeroMemory(m_szIP, sizeof(m_szIP));
	m_pController = NULL;
	m_hThread = NULL;
}

CMyNetwork::~CMyNetwork(void)
{
}

bool CMyNetwork::IsConnected()
{
	return s_server!=INVALID_SOCKET;
}
void CMyNetwork::Init(HWND hWnd)
{
	WSAData wsaData = {0};
	WSAStartup(MAKEWORD(2, 2), &wsaData);
	
}

int CMyNetwork::Init(void* pController, TCHAR* pszIP, UINT port)
{
	WSAData wsaData = {0};
	WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (m_hThread)
	{
		CloseHandle(m_hThread);
		m_hThread = NULL;
	}
	if (s_server)
	{
		closesocket(s_server);
		s_server = INVALID_SOCKET;
	}

	m_pController = pController;

	USES_CONVERSION;
	strcpy_s(m_szIP, sizeof(m_szIP), T2A(pszIP));

	m_nPort = port;


	CMyLog log;
	s_server = socket(AF_INET, SOCK_STREAM, 0);
	if (s_server == INVALID_SOCKET) {
		log.Msg("Error at socket(): %ld\n", WSAGetLastError());
		return -1;
	}

	sockaddr_in sin = {0};
	sin.sin_family = AF_INET;
	sin.sin_port = htons(m_nPort);
	sin.sin_addr.s_addr = inet_addr(m_szIP);

	if (connect(s_server, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)
	{
		// Error MSG: connect
		closesocket(s_server);
		s_server = INVALID_SOCKET;
		log.Msg("Error at cnnect(): %ld\n", WSAGetLastError());
		return -1;
	}

	unsigned int tid = 0;
	m_hThread = (HANDLE)_beginthreadex(NULL, 0, &ThreadProc, (LPVOID)this, 0, &tid);
	if (m_hThread == NULL)
	{
		log.Msg("Error on beginthread: %d", GetLastError());
		closesocket(s_server);
		s_server = INVALID_SOCKET;
		return -1;
	}

	return 0;
}

void CMyNetwork::Run()
{
	//*	struct fd_set fds; 
	struct timeval timeout={3, 0}; // wait 3 seconds, set 0 for non block
	FD_SET rfds;

	while(1) 
	{
		FD_ZERO(&rfds);
		FD_SET(s_server, &rfds);
	
		switch(select(0, &rfds, NULL, NULL, &timeout))
		{
		case SOCKET_ERROR:
			{
				CMyLog log;
				log.Msg("Error in network thread select : %ld\n", WSAGetLastError());
			}
			return ;
			break;
		case 0:		// time out
			break;
		default:
			if(FD_ISSET(s_server, &rfds)) // check data
			{
				ReceiveData();
			}
		}
	}
	//*/

	return;
}

//CreateFileMapping
//blen|type|body
void CMyNetwork::ReceiveData()
{
	int len = 0;
	int blen = 0;
	int ret = 0;
	unsigned char type = 0;
	recv(s_server, (char*)&blen, sizeof(int), 0);
	recv(s_server, (char*)&type, sizeof(unsigned char), 0);
	if (type == 0)
	{
		closesocket(s_server);
		s_server = INVALID_SOCKET;
	}
	blen = ntohl(blen);
	char *buf = new char[blen];
	memset(buf, 0, blen*sizeof(char));
	ret = recv(s_server, buf, blen, 0);
	if (ret > 0)
		((IController*)m_pController)->OnResponse(type, buf, blen);
	else
		;// add data buffer and len.

	if (type == RNPT_LOGOUT)
	{
		closesocket(s_server);
		s_server = INVALID_SOCKET;
		CloseHandle(m_hThread);
	}
}

void CMyNetwork::Login(LPCTSTR lpszUserName, LPCTSTR lpszPassword)
{
	char buf[256] = {0};
	CByteStream bs((unsigned char*)buf);
	bs<<(short)NPT_LOGIN;
	bs<<lstrlen(lpszUserName);
	bs.Write((void*)lpszUserName, lstrlen(lpszUserName));
	bs<<lstrlen(lpszPassword);
	bs.Write((void*)lpszPassword, lstrlen(lpszPassword));

	Send((char*)bs.GetData(), bs.Tell());

}

void CMyNetwork::Close()
{
	WSACleanup();
}

int CMyNetwork::Send(char* pszData, UINT len)
{
	CMyLog().PHex(pszData, len);
	if (send(s_server, (char*)pszData, len, 0) == SOCKET_ERROR)
	{
		CMyLog log;
		log.Msg("Error at send : %d", WSAGetLastError());
	}
	return 0;
}
